const NoteApp = require('./note.js');

describe('NoteApp', () => {
  let noteApp;

  beforeEach(() => {
    noteApp = new NoteApp();
  });

  describe('addNote', () => {
    test('should add a new note', () => {
      const note = noteApp.addNote('Test Title', 'Test Content');
      
      expect(note).toBeDefined();
      expect(note.id).toBe(1);
      expect(note.title).toBe('Test Title');
      expect(note.content).toBe('Test Content');
      expect(note.createdAt).toBeDefined();
      expect(note.updatedAt).toBeDefined();
    });

    test('should increment ID for multiple notes', () => {
      const note1 = noteApp.addNote('Title 1', 'Content 1');
      const note2 = noteApp.addNote('Title 2', 'Content 2');
      
      expect(note1.id).toBe(1);
      expect(note2.id).toBe(2);
    });
  });

  describe('getAllNotes', () => {
    test('should return empty array when no notes', () => {
      const notes = noteApp.getAllNotes();
      expect(notes).toEqual([]);
    });

    test('should return all notes', () => {
      noteApp.addNote('Title 1', 'Content 1');
      noteApp.addNote('Title 2', 'Content 2');
      
      const notes = noteApp.getAllNotes();
      expect(notes).toHaveLength(2);
      expect(notes[0].title).toBe('Title 1');
      expect(notes[1].title).toBe('Title 2');
    });
  });

  describe('getNoteById', () => {
    test('should return note by ID', () => {
      const addedNote = noteApp.addNote('Test Title', 'Test Content');
      const foundNote = noteApp.getNoteById(1);
      
      expect(foundNote).toEqual(addedNote);
    });

    test('should return undefined for non-existent ID', () => {
      const foundNote = noteApp.getNoteById(999);
      expect(foundNote).toBeUndefined();
    });
  });

  describe('updateNote', () => {
    test('should update existing note', () => {
      noteApp.addNote('Original Title', 'Original Content');
      const updatedNote = noteApp.updateNote(1, 'Updated Title', 'Updated Content');
      
      expect(updatedNote.title).toBe('Updated Title');
      expect(updatedNote.content).toBe('Updated Content');
      expect(updatedNote.id).toBe(1);
    });

    test('should update only title when content is not provided', () => {
      noteApp.addNote('Original Title', 'Original Content');
      const updatedNote = noteApp.updateNote(1, 'Updated Title');
      
      expect(updatedNote.title).toBe('Updated Title');
      expect(updatedNote.content).toBe('Original Content');
    });

    test('should return null for non-existent note', () => {
      const result = noteApp.updateNote(999, 'Title', 'Content');
      expect(result).toBeNull();
    });
  });

  describe('deleteNote', () => {
    test('should delete existing note', () => {
      noteApp.addNote('Test Title', 'Test Content');
      const deletedNote = noteApp.deleteNote(1);
      
      expect(deletedNote.title).toBe('Test Title');
      expect(noteApp.getAllNotes()).toHaveLength(0);
    });

    test('should return null for non-existent note', () => {
      const result = noteApp.deleteNote(999);
      expect(result).toBeNull();
    });
  });

  describe('searchNotes', () => {
    beforeEach(() => {
      noteApp.addNote('JavaScript Tutorial', 'Learn JavaScript basics');
      noteApp.addNote('Python Guide', 'Python programming guide');
      noteApp.addNote('Web Development', 'HTML, CSS, and JavaScript');
    });

    test('should find notes by title', () => {
      const results = noteApp.searchNotes('JavaScript');
      expect(results).toHaveLength(2);
      expect(results[0].title).toBe('JavaScript Tutorial');
      expect(results[1].title).toBe('Web Development');
    });

    test('should find notes by content', () => {
      const results = noteApp.searchNotes('Python');
      expect(results).toHaveLength(1);
      expect(results[0].title).toBe('Python Guide');
    });

    test('should be case insensitive', () => {
      const results = noteApp.searchNotes('javascript');
      expect(results).toHaveLength(2);
    });

    test('should return empty array when no matches', () => {
      const results = noteApp.searchNotes('nonexistent');
      expect(results).toHaveLength(0);
    });
  });
});
